var angular = require('angular');
var probe = require('../global');

probe.service("Capture", function (uniqueSelector, $rootScope) {
	var rootTop, rootLeft, $axes,
		isCrossIframe = true,
		selectedElement = null,
		iframeStack = [],
		contextRect = null,
		$area = angular.element('<div class="area"></div>').css('display', 'none'),
		rootContext = window.document,
		catchElementFn = angular.noop;

	function queryPointer(left, top) {
		var iframe, rect, doc,
			oLeft = 0, oTop = 0,
			element = rootContext.elementFromPoint(left, top);

		iframeStack = [];

		while (isCrossIframe && element && element.tagName === "IFRAME") {
			iframeStack.push(iframe = element);
			rect = iframe.getBoundingClientRect();
			doc = iframe.contentDocument;
			element = doc.elementFromPoint(left -= rect.left, top -= rect.top);
			oLeft += rect.left + iframe.clientLeft;
			oTop += rect.top + iframe.clientTop;
		}

		return {
			element: element,
			oLeft: oLeft,
			oTop: oTop
		};
	}

	function markElement(left, top) {
		var resolved = queryPointer(left, top),
			currentElement = resolved.element;

		if (!currentElement) {
			hideArea();
		} else if (selectedElement !== currentElement) {
			selectedElement = currentElement;
			showArea(resolved);
		}
	}

	function showArea(resolved) {
		//offset within iframe of itself.
		var rect = selectedElement.getBoundingClientRect();

		// -2px for border of <div class="area">
		$area.css({
			display: 'block',
			top: rect.top + resolved.oTop - 2 + 'px',
			left: rect.left + resolved.oLeft - 2 + 'px',
			width: rect.width + 'px',
			height: rect.height + 'px'
		});
	}
	
	function hideArea() {
		$area.css('display', 'none');
	}

	function unloadCaptureField() {
		$axes.css('display', 'none');
		selectedElement = null;
		rootContext = window.document;
		catchElementFn = angular.noop;
		isCrossIframe = true;
	}

	function loadCaptureField(rect) {
		$axes.css({
			display: 'block',
			top: rect.top + 'px',
			left: rect.left + 'px',
			height: rect.height + 'px',
			width: rect.width + 'px'
		});
		selectedElement = null;
	}

	function resolveSelector() {
		var iframePath, cssPath, selectorStack = [];

		iframeStack.forEach(function (element) {
			selectorStack.push(uniqueSelector.gen(element));
		});

		iframePath = selectorStack.join(' < ');
		elementPath = uniqueSelector.gen(selectedElement);

		cssPath = selectorStack.length ? iframePath + ' < ' + elementPath : elementPath;

		return cssPath;
	}

	function buildCaptureField(params) {
		var $ = angular.element,
			$axes = $('<div id="axes"></div>'),
			$axesX = $('<hr id="axes-x" />'),
			$axesY = $('<hr id="axes-y" />'),
			xStyle = $axesX[0].style,
			yStyle = $axesY[0].style;

		$axes.css({
			zIndex: 550,
			display: 'none'
		}).append($axesX).append($axesY).append($area);

		$axes.on('mousemove', function (event) {
			var left = event.clientX - contextRect.left,
				top = event.clientY - contextRect.top;
			
			// render moving (x, y)
			xStyle.left = left + "px";
			yStyle.top = top + "px";

			markElement(left, top);
		});

		$axes.on('click', function () {
			if (!selectedElement) { return; }
			catchElementFn(resolveSelector(), selectedElement);
			unloadCaptureField();
			$rootScope.$apply();
		});

		$axes.on('contextmenu', function (e) {
			e.preventDefault();
			unloadCaptureField();
		});
		$(window.document.body).append($axes);

		return $axes;
	}

	$axes = buildCaptureField();

	return function (catchFn, contextFrame, isNotCross) {
		isCrossIframe = !isNotCross;

		contextRect = contextFrame.getBoundingClientRect();
		rootContext = contextFrame.contentDocument;
		
		loadCaptureField(contextRect);
		catchElementFn = catchFn || angular.noop;
	};
});
